﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="EnsureSiteColumn.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Creates or Updates a Content Type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Collaboris.Saf.Actions.Wss.Column
{
    using System.Collections.Generic;
    using System.Xml;

    using Entities;

    using Engine;

    using SharePoint.Wss.Attributes;
    using SharePoint.Wss.Columns;

    [CollaborisClass(Title = "Ensure Site Column", ReleaseStatus = ReleaseStatus.Stable, DisableDocumentation = false, 
        ContactAuthorEmail = "Support@Collaboris.co.uk", 
        Summary =   "Adds or updates a SharePoint site column (allows the GUID to be specified for new columns).", 
        Remarks =   "The CAML that this action deals with " +
                    "must conform to the the standard schema defined in the namespace at : " +
                    "http://schemas.microsoft.com/sharepoint/." +
                    @"<br/><br/>For more information please read '<a href=""http://www.collaboris.co.uk/blogs/09-05-16/Upgrading_Site_Columns.aspx"">Upgrading Site Columns</a>'",
        ClassGuid = "{156E17A5-A7BA-4e1f-8A48-1BC341A7C632}",
        SupportFiles = new string[] { @"Column\Elements.xml", @"Column\Elements_Update.xml" }
    )]
    public class EnsureSiteColumn : WSSActionBase<ElementsInfo>
    {
        #region Constants and Fields

        /// <summary>
        /// Contains the CAML Elements file.
        /// </summary>
        private XmlDocument camlDoc;

        #endregion

        #region Helper Methods

        /// <summary>
        /// Executes the Action using the values passed in by the Data Entity
        /// and the <see cref="SafContext"/>.
        /// </summary>
        /// <param name="context">
        /// A valid <see cref="SafContext"/> containing properties to run the Action with.
        /// </param>
        /// <param name="entity">
        /// A Valid <see cref="ElementsInfo"/> containing the parameters with which to run the Action with.
        /// </param>
        /// <returns>
        /// A <see cref="ProcessStatus"/> signifying the outcome of processing the Action.
        /// </returns>
        protected override ProcessStatus DoAction(SafContext context, ElementsInfo entity)
        {
            ProcessStatus status = this.RunEnsureSiteColumn(entity, context);

            this.Trace.TraceMethodEnd("ProcessAction()");

            return status;
        }

        /// <summary>
        /// Checks the Data entity used by the Action for Validity
        /// </summary>
        /// <param name="context">
        /// The <see cref="SafContext"/> passed in by the SAF Engine.
        /// </param>
        /// <param name="entity">
        /// The data entity to Validate.
        /// </param>
        /// <param name="errors">
        /// List of <see cref="ValidationError"/>s
        /// </param>
        /// <param name="mode">
        /// <see cref="ProcessMode"/>signalling wheter we are Doing, or Undoing the action.
        /// </param>
        /// <returns>
        /// false if invalid; otherwise true.
        /// </returns>
        protected override bool IsValid(
            SafContext context, ElementsInfo entity, ref List<ValidationError> errors, ProcessMode mode)
        {
            int currentCount = errors.Count;

            // Validate each object now.
            ValidateStringForNull(entity.FilePath, "ElementsInfo.FilePath", ref errors);
            // ValidateBoolForNull(entity.PushChangesToList, "ElementsInfo.PushChangesToList", ref errors);
            // ValidateBoolForNull(entity.RemoveInChild, "ElementsInfo.RemoveInChild", ref errors);


            // read in the Content Type
            this.camlDoc = new XmlDocument();
            this.camlDoc.Load(entity.FilePath);

            // TODO: Can we get hold of the schema here and validate ?            

            // Have we added errors ?
            return errors.Count == currentCount;
        }

        /// <summary>
        /// Runs the ensure site column.
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <returns>
        /// false if invalid; otherwise true.
        /// </returns>
        private ProcessStatus RunEnsureSiteColumn(ElementsInfo entity, SafContext context)
        {
            this.Trace.TraceMethodStart("RunEnsureSiteColumn");

            ProcessStatus status;

            // open the file with CAML in it 
            this.Trace.TraceVerbose("Starting to Parse {0}", entity.FilePath);

            // TODO: ContinueOnError ?
            bool rc = SiteColumnHelper.SaveSiteColumn(
                context.Web, this.camlDoc, entity.RemoveInChild.Value, this.StopOnDoException);

            if (rc)
            {
                status = ProcessStatus.Success;
            }
            else
            {
                status = ProcessStatus.Warning;
            }

            context.Web.Update();

            this.Trace.TraceMethodEnd("RunEnsureSiteColumn");

            return status;
        }

        #endregion
    }
}